﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LinqExpressions = System.Linq.Expressions;
using Infinity.Expressions.LexicalParser;
using Infinity.Expressions.Extension;
using System.Linq.Expressions;

namespace Infinity.Expressions.Core
{
	public abstract class AbstractProgram
	{
		public AbstractProgram()
		{
		}

		/// <summary>
		/// A szintaxisfában ez maga az absztrakt programnak a reprezentációja.
		/// </summary>
		protected abstract Expression BodyExpression { get; }

		/// <summary>
		/// Az előfeltétel ellenőrzésére szolgál.
		/// </summary>
		protected virtual Expression PreValidate()
		{
			if (PreCondition != null)
			{
				return ConditionTest(PreCondition, Expression.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expression.Constant("prevalidate hiba")));
			}
			else
			{
				return Expression.Empty();
			}
		}

		/// <summary>
		/// Az utófeltétel ellenőrzésére szolgál. 
		/// </summary>
		protected virtual Expression PostValidate()
		{
			if (PostCondition != null)
			{
				return ConditionTest(PostCondition, Expression.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expression.Constant("postvalidate hiba")));
			}
			else
			{
				return Expression.Empty();
			}
		}

		/// <summary>
		/// Feltétel tesztelésére szolgáló függvény.
		/// </summary>
		protected Expression ConditionTest(Expression test, Expression body)
		{
			return Expression.IfThen(Expression.Equal(test, Expression.Constant(false)),
				//Expression.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(String) }), Expression.Constant("prevalidate hiba"))
						body
					);
		}

		/// <summary>
		/// Lexikai elemző
		/// </summary>
		public static ILexicalParser LexicalParser { get; set; }

		/// <summary>
		/// Előfeltétel
		/// </summary>
		/// 
		public LinqExpressions.Expression PreCondition { get; set; }
		/// <summary>
		/// Utófeltétel
		/// </summary>
		public LinqExpressions.Expression PostCondition { get; set; }

		public virtual void Parse(string text) { }

		/// <summary>
		/// Ezzel a parancssal lehet lefuttatni a tényleges programot. 
		/// </summary>
		public abstract void Run();

		/// <summary>
		/// Absztrakt program konvertálása Expression-né.
		/// </summary>
		public virtual Expression ToExpression()
		{
			return Expression.Block(PreValidate(), BodyExpression, PostValidate());
		}
	}
}
